<?

class db_mysql
{
	private static $handle;
	private static $connection = 'mysql';
	
	public static $local_cache = true;
	public static $cache;

	/**
	 * @return PDO
	 */
	public static function connection($connection = null)
	{
		if ( !$connection ) $connection = self::$connection;

		if ( !self::$handle[$connection] )
		{
			$conf = config::get($connection);
			
			if ( $conf['persist'] ) $attrs[PDO::ATTR_PERSISTENT] = true;

			$params = "mysql:host={$conf['host']}";
			$conf['db'] ? $params .= ";dbname={$conf['db']}" : '';
			$conf['port'] ? $params .= ";port={$conf['port']}" : '';

			self::$handle[$connection] = new PDO($params, $conf['user'], $conf['password'], $attrs);
			self::$handle[$connection]->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

			if ( $conf['charset'] ) self::$handle[$connection]->query('SET NAMES ' . $conf['charset']);
		}

		return self::$handle[$connection];
	}
	
	public static function disable_local_cache()
	{
		self::$local_cache = false;
	}
	
	public static function cache( $key, $value = null )
	{
		if ( !self::$local_cache ) return null;
		
		if ( $value === null ) return self::$cache[$key];
		self::$cache[$key] = $value;
	}

	public static function reconnect($connection = null)
	{
		if ( !self::$handle ) return;
		if ( !$connection ) $connection = self::$connection;
		self::$handle[$connection] = null;
		self::connection($connection);
	}

	public static function set_connection( $name = null )
	{
		self::$connection = $name ? $name : 'mysql';
	}

	public static function last_id($name = null)
	{
		return self::connection($name)->lastInsertId();
	}

	/**
	 * @return PDOStatement
	 */
	public static function query($sql, $params = array(), $connection = null)
	{
		$s = self::connection($connection)->prepare($sql);
		$s->execute($params);
		return $s;
	}

	public static function get_row( $params_sql, $table = null, $connection = null )
	{
		if ( is_array($params_sql) )
		{
			foreach ( $params_sql as $k => $v )
			{
				$keys[] = "`{$k}` = :{$k}";
				$vals[":{$k}"] = $v;
			}

			$sql = "SELECT * FROM {$table} WHERE " . implode($keys, ' AND ') . " LIMIT 1";
		}
		else
		{
			$sql = $params_sql;
			$vals = $table;
		}

		return self::query($sql, $vals, $connection)->fetch(PDO::FETCH_ASSOC);
	}

	public static function get_rows( $params_sql, $table = null, $connection = null )
	{
		if ( is_array($params_sql) )
		{
			foreach ( $params_sql as $k => $v )
			{
				$keys[] = "{$k} = :{$k}";
				$vals[":{$k}"] = $v;
			}

			$sql = "SELECT * FROM {$table} " . ( $keys ? " WHERE " . implode($keys, ' AND ') : '' );
		}
		else
		{
			$sql = $params_sql;
			$vals = $table;
		}

		return self::query($sql, $vals, $connection)->fetchAll(PDO::FETCH_ASSOC);
	}

	public static function get_cols( $params_sql, $table = null, $column = '*', $connection = null )
	{
		if ( is_array($params_sql) )
		{
			foreach ( $params_sql as $k => $v )
			{
				$keys[] = "{$k} = :{$k}";
				$vals[":{$k}"] = $v;
			}

			$sql = "SELECT {$column} FROM {$table} " . ( $keys ? " WHERE " . implode($keys, ' AND ') : '' );
		}
		else
		{
			$sql = $params_sql;
			$vals = $table;
		}

		return self::query($sql, $vals, $connection)->fetchAll(PDO::FETCH_COLUMN);
	}

	public static function get_scalar( $params_sql, $table = null, $key = '*', $connection = null )
	{
		if ( is_array($params_sql) )
		{
			foreach ( $params_sql as $k => $v )
			{
				$keys[] = "{$k} = :{$k}";
				$vals[":{$k}"] = $v;
			}

			$sql = "SELECT {$key} FROM {$table} WHERE " . implode($keys, ' AND ') . " LIMIT 1";
		}
		else
		{
			$sql = $params_sql;
			$vals = $table;
		}

		return self::query($sql, $vals, $connection)->fetch(PDO::FETCH_COLUMN);
	}

	public static function insert( $data, $table, $replace = false, $connection = null )
	{
		foreach ( $data as $k => $v )
		{
			$keys[] = ":{$k}";
			$vals[":{$k}"] = $v;
		}

		$sql = ( $replace ? 'REPLACE' : 'INSERT' ) . " INTO {$table}(`" . implode('`, `', array_keys($data)) . "`) VALUES(" . implode(', ', $keys) . ')';

		return self::query($sql, $vals, $connection);
	}

	public static function update( $data, $params, $table, $connection = null )
	{
		foreach ( $data as $k => $v )
		{
			$keys[] = "`{$k}` = :{$k}";
			$vals[":{$k}"] = $v;
		}

		foreach ( $params as $k => $v )
		{
			$pars[] = "`{$k}` = :{$k}";
			$vals[":{$k}"] = $v;
		}

		$sql = "UPDATE {$table} SET " . implode($keys, ', ') . ' WHERE ' . implode($pars, ' AND ');
		return self::query($sql, $vals, $connection);
	}

	public static function delete( $data, $table, $single = false, $connection = null )
	{
		foreach ( $data as $k => $v )
		{
			$keys[] = "`{$k}` = :{$k}";
			$vals[":{$k}"] = $v;
		}

		$sql = "DELETE FROM {$table} WHERE " . implode($keys, ' AND ') .
				( $single ? ' LIMIT 1' : '' );

		return self::query($sql, $vals, $connection);
	}
}